/*
 * MedianEvaluator.java
 *
 * Copyright (C) 2014 Fabian Wenzelmann
 *
 * This file is part of stura_voting.
 *
 * stura_voting is free software: you
 * can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * stura_voting is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 * Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with stura_voting.
 *
 * If not, see <http://www.gnu.org/licenses/>.
 */

package de.stura.median;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Collections;

/**
 * A class to evaluate a median ballot.
 */
public class MedianEvaluator {
    
    public MedianEvaluator() { }
    
    /**
     * Evaluate all votes and return the selected value.
     * 
     * This will change the order of the entries in votes (by sorting them).
     * If something goes wrong it returns null, but this should usually never happen.
     */
    public Float evaluate(ArrayList<MedianVote> votes) {
        int weightSum = 0;
        for (MedianVote v : votes) {
            weightSum += v.getWeight();
        }
        // required votes is the variable we must EXCEED
        // a small example: if we have 8 votes and all have
        // weight 1 we need 5 votes = 8 / 2 = 4, i.e. > 4 votes
        // if we have 9 votes we also need 5. 9 / 2 = 4, i.e. > 4 votes
        int requiredVotes = weightSum / 2;
        Comparator<MedianVote> comp = new Comparator<MedianVote>() {
            public int compare(MedianVote v1, MedianVote v2) {
                // highest votes in front
                if (v1.getValue() > v2.getValue()) {
                    return -1;
                }
                else if (v1.getValue() < v2.getValue()) {
                    return 1;
                }
                // equal
                return 0;
            }
        };
        Collections.sort(votes, comp);
        int weightSoFar = 0;
        for (MedianVote v : votes) {
            weightSoFar += v.getWeight();
            // TODO > or >=?
            if (weightSoFar > requiredVotes) {
                return v.getValue();
            }
        }
        return null;
    }
}
